package org.mbari.vcr;

import java.util.Timer;
import org.mbari.util.IObserver;

/**
 * Base class for observers that respond to the state of the VCR. These
 * observers send commands to the VCR at regular intervals.
 */
public abstract class StateObserver implements IObserver {
    
    /**
	 * @uml.property  name="intervalMin"
	 */
    protected long intervalMin = 33;
    /**
	 * @uml.property  name="interval"
	 */
    protected long interval = intervalMin;
    
    /**
	 * This timer is used to read timecode at regular intervals
	 * @uml.property  name="timer"
	 */
    Timer timer;
    
    public void update(Object obj, Object changeCode) {
        IVCRState state = (IVCRState) obj;
        if (state.isStopped() || state.isStill()) {
            stopTimer();
        } else {
            startTimer();
        }
    }
    
    /**
     * <p>Use this method to set the type of task you will use. We could have
     *  used reflection and just have a user set the Class of the TimerTask
     *  to instantiate, but reflection is slow and the VCR application is
     *  a time-sensitive process. The code implemented should look something like
     *  this:</p> 
     *  <pre>
     *  void startTimer() {
     *      if (getTimer() == null) {
     *          setTimer(new Timer(true));
     *          // TimerTask is an impementation of java.util.TimerTask
     *          getTimer().schedule(new MyTimerTask(), 0, getInterval());
     *      }
     *  }
     *  </pre>
     */
    abstract void startTimer();
    
    void stopTimer() {
        if (getTimer() != null) {
            getTimer().cancel();
            setTimer(null);
        }
    }
    
    /**
	 * @return  the timer
	 * @uml.property  name="timer"
	 */
    Timer getTimer() {
        return timer;
    }
    
    /**
	 * @param timer  the timer to set
	 * @uml.property  name="timer"
	 */
    void setTimer(Timer timer) {
        this.timer = timer;
    }
    
    /**
	 * @return  the interval
	 * @uml.property  name="interval"
	 */
    public long getInterval() {
        return interval;
    }
    
    /**
	 * @param interval  the interval to set
	 * @uml.property  name="interval"
	 */
    public void setInterval(long interval) {
        if (interval < intervalMin) {
            interval = intervalMin;
        }
        boolean reset = interval != this.interval;
        this.interval = interval;
        if (reset && getTimer() != null) {
            stopTimer();
            startTimer();
        }
    }
}